import os, string, traceback
import vcs
from logParser import Revision

from vcs import TEST, TRUE, FALSE, NL, SYSTEM, WINDOWS, UNIX, NULLDEV, SHELL, clr_output

mod="(CCMlog) "


# ----------------------------------------------------
# ---- util functions --------------------------------
# ----------------------------------------------------

# like vcs.system, but returns rc and out
def system(cmd):
	clr_output()
	if SYSTEM==WINDOWS:
		# Shell command wrapped in "-quotation. We need '-quotation inside of command
		# cmd = '%s -c \'%s\'' % (SHELL, cmd)
		cmd = '%s -c "%s"' % (SHELL, cmd)
	if TEST: print "System:", cmd
	rc, _out = vcs.syscmd(cmd)
	return rc, _out

def PrintErrorLog(cmd, rc, out, err):
	print 'ERROR'
	print 'Command:', cmd
	print 'Return Code:', rc
	print 'Error:', err
	print 'Output:', out
	print 'END OF ERROR LOG'


# ----------------------------------------------------
# ---- Continuus log class ---------------------------
# ----------------------------------------------------
class CCMlog:
	workFiles = []
	workFile = ''
	count = 0
	valid = TRUE
	CMD		= "ccm history -f '"
	CMD = CMD + "Object:    %name "
	CMD = CMD + "|Version:  %version "
	CMD = CMD + "|Owner:    %owner "
	CMD = CMD + "|State:    %status "
	CMD = CMD + "|Modified: %modify_time "
	CMD = CMD + "|Task:     %task %task_synopsis "
	CMD = CMD + "|Comment:  %comment "
	# take care of this last line... whatch the |" and space after!
	CMD = CMD + "|Release:  %release |' "

	CURRCMD = "ccm attr -s version "
	logText = ''

	def __init__(self, workFile):
		marker=mod+"__init__"
		self.workFiles = string.split(workFile, ' ')
		if TEST: print marker, self.workFiles
		self.workFile = workFile
		self.count = 0
		self.valid = TRUE
		# self.workingRelease = self.readConfigFile(self.WorkReleaseFile)
		# self.workarea = self.readConfigFile(self.WorkAreaFile)
		# if TEST: print marker, "WorkingRelease: ", self.workingRelease, ", WorkArea: ", self.workarea,
		self.next()

	def next(self):
		marker=mod+"next: "
		try:
			self.workFile = self.workFiles[self.count]
		except:
			if TEST: print marker, "End of files reached!"
			self.valid = FALSE
			return
		cmd = self.CMD + "'" + self.workFile + "'"
		rc, result = system(cmd)

		if not result[:7] == "Object:":
			#self.versionList = []
			#self.valid = FALSE
			#return FALSE
			# return a dummy history
			self.versionList = []
			self.count = self.count + 1
			return
		self.versionList = string.split(result, 77*'*')
		if not string.strip(self.versionList[-1]):
			del self.versionList[-1]
		# if TEST: print marker, "logText: ", self.logText
		self.count = self.count + 1
		
	def __nonzero__(self):
		return self.valid
	
	def is_last_file(self):
		# returns whether this is the last in a list of files or
		# whether there are more.
		nFiles = len(self.workFiles)
		if TEST: print "@rlast_file:", nFiles, self.count
		if nFiles == 1 or self.count >= nFiles: 
			return TRUE
		return FALSE
	
	def getText(self):
		return string.join(self.logText, 10*'*')

	def work_file(self):
		return self.workFile

	def lockers(self):
		marker=mod+"lockers: "
		cmd = self.CURRCMD + "'" + self.workFile + "'"
		rc, result = system(cmd)
		theRev = string.strip(result)
		theStart = string.find(self.logText, NL+"locks:"+NL)
		if theStart <= 0:
			return ''
		theLockers = ""
		lockerList = string.split(self.logText[theStart+1:], NL)
		if TEST: print marker, lockerList
		try:
			for curLine in lockerList[3:]:
				if not curLine:
					break
				curList = string.split(string.strip(curLine))
				newLockers = "%s: %s " % (curList[0], self.convert_rev(curList[2]))
				theLockers = theLockers + newLockers
		except:
			if TEST:
				print marker, "Exception caught, Parsing Error? ", lockerList
				traceback.print_exc()
			pass
		return theLockers

		return ""

	def head_rev(self):
		# simple: return the highest numerical integer version number found.
		# It would be nicer to return either the highest number of the current
		# release, or to look only at revisions which don't have successors.
		marker=mod+"head_rev: "
		if not self.versionList:
			# file was not yet checked in
			return "1.1"
		try:
			highestVersion=0
			for curVerText in self.versionList:
				curVersion = string.split(curVerText, '|')
				version = string.strip(curVersion[1][10:])
				release = string.strip(curVersion[7][10:])
				try:
					numVersion = int(version)
				except:
					numVersion = 0
				if numVersion > highestVersion:
					highestVersion = numVersion
		except:
			print "Error in head_rev:"
			traceback.print_exc()
			print "@rx",curVerText,"x"
			print self.versionList
		return "1."+str(highestVersion)
	
	def symbolstr(self):
		# here we'd like to supply change sets...
		marker=mod+"symbolstr: "
		if TEST: print marker
		if not self.versionList:
			# file was not yet checked in
			return ""
		cmd = self.CURRCMD + "'" + self.workFile + "'"
		rc, result = system(cmd)
		theRev = string.strip(result)
		if TEST: print marker, theRev
		# SNiFF NEEDS RCS-like revision IDs with 1.x
		result='WA_CURRENT: '+"1."+theRev+NL
		try:
			for curVerText in self.versionList:
				curVersion = string.split(curVerText, '|')
				version = string.strip(curVersion[1][10:])
				task = string.strip(curVersion[5][10:])
				if len(task) >= 6 and task[:6] != "<void>":
					tr = string.maketrans(" *,:;?.!#$",10*"_")
					realTask = string.translate(task,tr)
					result = result + "SNIFF_CHANGESET_Task"+realTask+": "+"1."+version+NL
		except:
			import traceback
			traceback.print_exc()
		if result: 
			return result[:-1]
		else:
			return ""
	
	def history_str(self):
		return string.join(self.versionList, 10*'*')
		return ''
	
	def revision(self, want_rev):
		# Q: is want_rev a symbolic or internal RCS-like one ???
		if not self.versionList:
			# file was not yet checked in
			result = Revision("1.1")
			result.ccmrev = "not-yet-checked-in"
			return result
		for curVerText in self.versionList:
			curVersion = string.split(curVerText, '|')
			version = string.strip(curVersion[1][10:])
			if not version == want_rev:
				continue
			owner = string.strip(curVersion[2][10:])
			state = string.strip(curVersion[3][10:])
			modified = curVersion[4][10:]
			task = curVersion[5][10:]
			comment = string.strip(curVersion[6][10:])
			release = string.strip(curVersion[7][10:])
			curRev = Revision("1."+version)
			curRev.ccmrev = version
			curRev.author = owner
			#try:
			#	print modified
			#	modTime = time.strptime(modified)
			#	curRev.date = time.strftime("%Y/%m/%d %H:%M:%S",modTime)
			#except:
			#	curRev.date = "1999/06/01 12:00:00"
			curRev.date = modified
			curRev.state = state
			curRev.log_message = comment
			return curRev
		return None
		
	
	def revision_list(self):
		"""Returns a list of Revisions"""
		marker=mod+"revision_list: "
		result=[]
		if not self.versionList:
			# file was not yet checked in
			result = Revision("1.1")
			result.ccmrev = "not-yet-checked-in"
			return [result]
		try:
			for curVerText in self.versionList:
				curVersion = string.split(curVerText, '|')
				object = curVersion[0][10:]
				version = string.strip(curVersion[1][10:])
				owner = string.strip(curVersion[2][10:])
				state = string.strip(curVersion[3][10:])
				modified = curVersion[4][10:]
				task = curVersion[5][10:]
				comment = curVersion[6][10:]
				release = string.strip(curVersion[7][10:])
				# SNiFF+ needs internal RCS-like revisions with the following
				# properties: it must contain a "." and it must consist of at least
				# two numerical values. This internal revision is used for correctly
				# sorting and showing branches.
				# However, only the "symbolic revision" (ccmrev) is shown in the history
				# and presented to the user.
				curRev = Revision("1."+version)
				curRev.ccmrev = version
				curRev.author = owner
				try:
					modTime = time.strptime(modified)
					curRev.date = time.strftime("%Y/%m/%d %H:%M:%S",modTime)
				except:
					curRev.date = "1999/06/01 12:00:00"
				curRev.lines = state
				result = [curRev] + result
		except:
			if TEST:
				print marker
				traceback.print_exc()
				print "@rx",curVerText,"x"
				print self.versionList
			pass
		return result

if __name__ == "__main__":
	pass
